<?php

/**
 * This is the model class for table "tbl_contracts".
 *
 * The followings are the available columns in table 'tbl_contracts':
 * @property string $contractid
 * @property string $custno
 * @property string $locno
 * @property integer $contractype
 * @property string $orginalcontractid
 * @property string $contractamount
 * @property string $contractstartdate
 * @property string $contractenddate
 * @property integer $salesperson
 * @property string $jobno
 * @property integer $billtype
 * @property integer $status
 * @property string $lastdatebilled
 * @property string $lastaccuralpostperiod
 * @property string $invoiceemail
 * @property string $purchasedby
 * @property string $pre_quote_amount
 */
class Contracts extends CActiveRecord
{
    const TYPE_YEARLY=0;
    const TYPE_MONTHLY=1;
    const TYPE_QUARTERLY=2;
    private $counter = null;
    protected $_tax;
    protected $_isTaxNex = false;
    /**
     * Returns the static model of the specified AR class.
     * @return Contracts the static model class
     */
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'tbl_contracts';
    }

    public function getBillTypeList()
    {
        return array(
            self::TYPE_YEARLY => 'Yearly',
            self::TYPE_MONTHLY => 'Monthly',
            self::TYPE_QUARTERLY => 'Quarterly',
        );
    }

    public function getBillTypeText()
    {
        return isset($this->billTypeList[$this->billtype]) ? $this->billTypeList[$this->billtype] : NULL;
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('contractid, custno, locno, contractype, orginalcontractid, contractamount, contractstartdate, contractenddate, salesperson, jobno, billtype, lastdatebilled, lastaccuralpostperiod,pre_quote_amount', 'safe'),
            array('billingstatus,contractype, billtype', 'numerical', 'integerOnly' => true),
            array('contractid, orginalcontractid, jobno', 'length', 'max' => 41),
            array('salesperson', 'length', 'max' => 4),
            array('custno', 'length', 'max' => 7),
            array('locno', 'length', 'max' => 5),
            array('invoiceemail', 'length', 'max' => 255),
            array('area1accountno,area1description', 'length', 'max' => 9999),
            array('contractamount', 'length', 'max' => 10),
            array('invoiceemail', 'email', 'allowEmpty' => true),
            array('purchasedby', 'length', 'max' => 50),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('contractid,status, custno, locno, contractype, orginalcontractid, contractamount, contractstartdate, contractenddate, salesperson, jobno, billtype, lastdatebilled, lastaccuralpostperiod', 'safe'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'customer' => array(self::BELONGS_TO, 'Customers', 'custno'),
            'uninvoiceSchedulePayments'=>array(self::HAS_MANY, 'ContractQuarterly', 'contractid', 'order' => 'number','condition'=>'invoice=""'),                                    
            'schedulePaymentModelList'=>array(self::HAS_MANY,'ContractSchedule','contractid','order'=>'number'),
            'salesOrderList'=>array(self::HAS_MANY,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_SALES_ORDERS)),
            'salesOrderCount'=>array(self::STAT,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_SALES_ORDERS)),
            'quoteList'=>array(self::HAS_MANY,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_QUOTE)),
            'quoteCount'=>array(self::STAT,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_QUOTE)),
            'invoiceList'=>array(self::HAS_MANY,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_INVOICE)),
            'invoiceAndCMList'=>array(self::HAS_MANY,'Invoice','agreementno','condition'=>'invoicetype=:itype or invoicetype=:cmtype',
            'params'=>array('itype'=>Invoice::TYPE_INVOICE,'cmtype'=>  Invoice::TYPE_CREDIT_MEMO)),        
            'cmList'=>array(self::HAS_MANY,'Invoice','agreementno','condition'=>'invoicetype=:type','params'=>array('type'=>Invoice::TYPE_CREDIT_MEMO)),         
            'ledgerList'=>array(self::HAS_MANY,'ContractLedger','contractid'),
            'equipments'=>array(self::HAS_MANY,'ContractEquipment','contractid'),
            'softwareOptions'=>array(self::HAS_MANY,'ContractSofwareMaintLedger','contractid'),
            'invoiceCount'=>array(self::STAT,'Invoice','agreementno'),
                // 'location' => array(self::BELONGS_TO, 'Locations', 'custno,locno'),
        );
    }
    protected $_location;
    public function getLocation()
    {
        if($this->_location == null){
            $this->_location = Locations::model()->find('custno=:custno AND locno=:locno', array(
                    'custno' => $this->custno,
                    'locno' => $this->locno
                ));
        }
        return $this->_location;
    }
  
    

    public function getInvoiceList()
    {
        $list = Invoice::model()->findAll('agreementno=:agreementno AND invoicetype=:type', array(
            'agreementno' => $this->contractid,
            'type' => Invoice::TYPE_INVOICE
                ));
        return $list;
    }

    

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'contractid' => 'Contract ID',
            'custno' => 'Customer',
            'locno' => 'Location',
            'contractype' => 'Contract type',
            'orginalcontractid' => 'Orginal contract ID',
            'contractamount' => 'Equipment Amount',
            'contractstartdate' => 'Contract start date',
            'contractenddate' => 'Contract end date',
            'salesperson' => 'Sales person',
            'jobno' => 'Job #',
            'billtype' => 'Bill type',
            'lastdatebilled' => 'Last date billed',
            'lastaccuralpostperiod' => 'Last accural post period',
            'area1accountno' => 'Area 1 Account No',
            'area1description' => 'Area 1 Description',
            'invoiceemail' => 'Email',
            'purchasedby' => 'Purchased by',
            'pre_quote_amount'=>'Pre-Quote Amount'
        );
    }

    public function beforeValidate()
    {
        if($this->isNewRecord){
        
            if ($this->contractstartdate!=null)
            {
                $dateExp = explode('-', $this->contractstartdate);

                $this->counter = $dateExp[0] . '-contract';
                $this->contractid = $dateExp[0] . '-' . Counters::model()->getNextNumber($dateExp[0] . '-contract');
            }
            else
            {
                $this->counter = DateUtil::getDefaultYear().'-contract';
                $this->contractid = DateUtil::getDefaultYear() . '-' . Counters::model()->getNextNumber($this->counter);
            }
        }
        return parent::beforeValidate();
    }
    public function beforeSave()
    {
        if($this->isNewRecord == false)
        {
            $oldModel = $this->findByPk($this->contractid);
            if($oldModel->billtype != $this->billtype){
                $this->changeBillTypeEvent();
            }                        
        }
        return parent::beforeSave();
    }
    
    public function afterSave(){
        $this->createCItem();
        $this->createHISTItem();
        if ($this->isNewRecord && $this->counter!=null)
        {

            Counters::model()->saveNumber($this->counter);
        }
    }
    public function getStatusText()
    {
        return isset($this->StatusFullList[$this->status]) ? $this->StatusFullList[$this->status] : NULL;
    }

    public function getStatusFullList()
    {
        $data = CHtml::listData(ContractStatus::model()->findAll('inactive=0'), 'id', 'description');
        if (count($data) > 0)
        {
            return $data;
        }
        return NULL;
    }

    public static function getLocalList($custno, $locno)
    {
        $list = Contracts::model()->findAll('custno=:custno AND locno=:locno', array(
            'custno' => $custno,
            'locno' => $locno
                ));
        return Html::listData($list, 'contractid', 'contractid', true);
    }
    public function getScheduleLengthByBillType(){
        if($this->billtype==self::TYPE_MONTHLY){
            return 12;
        }else if($this->billtype==self::TYPE_QUARTERLY){
            return 4;            
        }
        return 0;
    }
    public function isScheduleContract(){
        return $this->billtype==self::TYPE_MONTHLY || $this->billtype==self::TYPE_QUARTERLY;
    }
    public function saveSchedulePayment()
    {
        $amount=$this->pre_quote_amount;
        if($this->isScheduleContract()){
            $count=$this->getScheduleLengthByBillType();
            $part = round($amount / $count, 2, PHP_ROUND_HALF_DOWN);
            $odd = $amount - ($part * ($count - 1));
            $increment = 12 / $count;

            $curMonth = new DateTime($this->contractstartdate);
            Yii::app()->db->createCommand()->delete('tbl_contract_schedule', 'contractid=:contractid and billtype!=:billtype', array(
                'contractid' => $this->contractid,
                'billtype'   => $this->billtype
            ));
            for ($i = 1; $i <= $count; $i++)
            {
                $item = Yii::app()->db->createCommand('select * from tbl_contract_schedule where number=:i and contractid=:contractid and billtype=:billtype')
                                ->bindValues(array(
                                    'i' => $i,
                                    'contractid' => $this->contractid,
                                    'billtype'=>$this->billtype
                                ))->queryRow();

                if ($item != NULL)
                {
                    if ($i != 1)
                    {
                        $curMonth->add(new DateInterval("P{$increment}M"));
                        $item['date'] = $curMonth->format('Y-m-d');
                    }
                    else
                    {
                        $item['date'] = $this->contractstartdate;
                    }
                    $item['amount'] = $i != 4 ? $part : $odd;
                    unset($item['id']);
                    Yii::app()->db->createCommand()->update('tbl_contract_schedule', $item, 'number=:i and contractid=:contractid', array(
                        'i' => $i,
                        'contractid' => $this->contractid
                            )
                    );
                }
                else
                {
                    $item['contractid'] = $this->contractid;
                    $item['billtype']=$this->billtype;
                    $item['amount'] = $i != $count ? $part : $odd;
                    if ($i != 1)
                    {
                        $curMonth->add(new DateInterval("P{$increment}M"));
                        $item['date'] = $curMonth->format('Y-m-d');
                    }
                    else
                    {
                        $item['date'] = $this->contractstartdate;
                    }
                    $item['number'] = $i;
                    $item['invoice'] = '';
                    Yii::app()->db->createCommand()->insert('tbl_contract_schedule', $item);
                }
            }
        }else{
            
        }
    }

    public function createScheduleInvoiceItem($invoice, $payment)
    {
        $partno = 'C-' . ContractType::getText($this->contractype);
        $inv = Inventory::model()->findByPk($partno);
        $pricecode = Yii::app()->db->createCommand('select pricecode from tbl_customers where custno=:custno')
                        ->bindValues(array('custno' => $this->custno))->queryScalar();
        if ($inv != NULL)
        {
            $model = new InvoiceLedger();
            $model->warehouse = '0000';
            $model->partno = $partno;
            $type = $this->getBillTypeText();
            if ($this->billtype == self::TYPE_YEARLY)
            {
                $model->description = "Annual " . ContractType::getText($this->contractype) . " Contract No. $this->contractid";
            }
            else
            {
                $model->description = "$payment->number $type Payment: Annual Service Contract No. $this->contractid";
            }
            $model->qty = 1;
            $model->cost = 0;
            $model->markupvalue = 190;
            $model->autoSetTaxed($this->custno);
            $model->noprint = 0;
            $model->tax1 = 0;
            $model->invoice = $invoice->invoice;
            $model->price = $inv->getPrice($pricecode);
            $model->price+=$payment->amount;

            if ($model->save())
            {
                return $model;
            }
        }


        return null;
    }
    public function countSalesOrder(){
        
    }
    
    public function hasEmptyScheduleSpace(){
        
    }
    public function canCreateScheduleInvoice(){
        if($this->isScheduleContract()
                && $this->quoteCount > 0 && $this->salesOrderCount >0){
           return true;
        }
        return false;
    }
    public function createFirstScheduleInvoice(){
        if($this->canCreateFirstScheduleInvoice()){
            return $this->createNextScheduleInvoice();
        }
        return false;
    }
    public function createNextScheduleInvoice(){
        $payment = $this->getNearestUnInvoicePayment();
        if($payment!==false){
            return $this->createScheduleInvoice($payment,false);
        }
        return false;
    }
    public function createScheduleInvoice(&$payment,$isCreatedByCron=false)
    {
       
        if ($this->canCreateScheduleInvoice() && $payment!==false)
        {
            $salesOrderList = $this->salesOrderList;            
            $location=$this->location;            
            $invoice = new Invoice;     
            $invoice->isCreatedByCron = $isCreatedByCron;
            $invoice->agreementno = $this->contractid;
            $invoice->invoicedate = $payment->date;
            $invoice->custno = $this->custno;
            $invoice->locno = $this->locno;
            $invoice->invoicetype = Invoice::TYPE_INVOICE;
            $invoice->salesperson = $this->salesperson;
            $invoice->department = $invoice->findDepartmentByContractType($this->contractype);
            $invoice->salesordersorg = $salesOrderList[0]->invoice;
            $invoice->quoteorg = $salesOrderList[0]->quoteorg;
            $invoice->shipname = $location->locname;
            $invoice->shipaddress1 = $location->add1;
            $invoice->shipaddress2 = $location->add2;
            $invoice->purchasedby = $this->purchasedby;
            $invoice->slterms=$this->customer->terms;
            $invoice->billloc = 0;
            $invoice->shipCSZ = $location->city . ' ' . $location->state . ' ' . $location->zip;
            if ($invoice->save())
            {
                $item = $this->createScheduleInvoiceItem($invoice, $payment);
                
                if ($item != null)
                {
                    $payment->invoice = $invoice->invoice;
                    $invoice->amountcharge = $item->price;
                    $payment->save();
                    $invoice->save();
                    return $invoice->invoice;
                }
            }
            
        }
        return false;
    }

    /**
     * Create a schedule item, partno is HIST for this contract
     * @return ContractLedger 
     */
    public function createHISTItem()
    {
        if ($this->isScheduleContract() || $this->contractype==1|| $this->contractype==4)
        {
            $partno = 'HIST';
            $inv = Inventory::model()->findByPk($partno);
            $pricecode = Yii::app()->db->createCommand('select pricecode from tbl_customers where custno=:custno')
                            ->bindValues(array('custno' => $this->custno))->queryScalar();
            if ($inv != NULL)
            {

                $model = ContractLedger::model()->find('contractid=:contractid AND partno=:partno', array(
                    'partno' => $partno,
                    'contractid' => $this->contractid
                        ));

                if ($model == NULL)
                {
                    $model = new ContractLedger();
                    $model->warehouse = '0000';
                    $model->partno = $partno;
                    $model->contractid = $this->contractid;
                    $type = $this->getBillTypeText();
                    $model->description = "Bill Type: $type " . "(Coverage - Start: {$this->contractstartdate} End: {$this->contractenddate})";
                    $model->qty = 1;
                    $model->cost = 0;
                    $model->markupvalue = 190;
                    $model->autoSetTaxed($this->custno);
                    $model->noprint = 0;
                    //$model->tax1 = 0;
                    $model->price = $inv->getPrice($pricecode);
                }
                if ($model->save())
                {
                    return $model;
                }
            }
        }

        return null;
    }

    /**
     * Create contract type ledger item, such as C-Service, C-Monitor...
     * @return ContractLedger 
     */
    public function createCItem()
    {
        $partno = 'C-' . ContractType::getText($this->contractype);
        $inv = Inventory::model()->findByPk($partno);
        $pricecode = Yii::app()->db->createCommand('select pricecode from tbl_customers where custno=:custno')
                        ->bindValues(array('custno' => $this->custno))->queryScalar();
        if ($inv != NULL)
        {

            $model = ContractLedger::model()->find('contractid=:contractid AND partno=:partno', array(
                    'partno' => $partno,
                    'contractid' => $this->contractid
                )
            );

            if ($model == NULL)
            {
                $model = new ContractLedger();
                $model->warehouse = '0000';
                $model->partno = $partno;
                $model->contractid = $this->contractid;
		$model->description = "Annual " . ContractType::getText($this->contractype) . " Contract No. $this->contractid";
                $model->qty = 1;
                $model->cost = 0;
                $model->markupvalue = 190;
                $model->taxed = 0;
                $model->noprint = 0;
                //$model->tax1 = 0;
                $model->autoSetTaxed($this->custno);                      
            }
            if($this->contractype==4){
                $price = 0;
                $cost = 0 ;
                $model->description = "Annual NCR Software Maint. Contract No:. $this->contractid";
                $softModels = ContractSofwareMaintLedger::model()->findAll("contractid = '$this->contractid'");
                foreach($softModels as $item){
                    $price+=$item->total_maintenance_price;
                    $cost+=$item->total_maintenance_rate;
                }
                $model->price = $price;
                $model->cost = $cost;
            } else{
                if($this->contractype==1){
                    $model->price =$this->contractamount;
                }else{
                    $model->price = $inv->getPrice($pricecode);
                }
            }
            $model->save();
            return $model;
            
        }


        return null;
    }

    public function canCreateFirstScheduleInvoice()
    {
        if($this->canCreateScheduleInvoice() && count($this->invoiceList)==0){
            return true;
        }
        return false;
    }

    public function getNearestUnInvoicePayment()
    {
        $schedulePayment=$this->schedulePaymentModelList;
        if(count($schedulePayment)>0){
            foreach($schedulePayment as $payment){
                if($payment->invoice==NULL){
                    return $payment;
                }
            }
        }
        return false;
    }
    public function getOnTimePayment(){
        $payment=$this->getNearestUnInvoicePayment();
        if($payment!==false){
            $paymentTime=strtotime($payment->date);
            if($paymentTime < time()){
                return $payment;
            }
            
        }
        return false;
    }
  
    public function deleteInvoiceFromSchedule($invoice)
    {
       
        Yii::app()->db->createCommand()->delete('tbl_contract_schedule', 'contractid=:contractid AND invoice=:invoice AND billtype=:type', array(
            'contractid' => $this->contractid,
            'invoice' => $invoice,
            'type'=>$this->billtype
        ));
      
        
    }

    public function getTaxValue(){
        $model = $this->getTaxModel();
        if($model!=null){
            if($this->isTaxNex()){
                return $model->nextaxrate;
            }else{
                return $model->salestaxrate;
            }
        }
        return 0;

    }
  
      public function createSoftHist(){
        $partno = 'HIST1';
        $model = ContractLedger::model()->find('contractid=:contractid AND partno=:partno', array(
            'partno' => $partno,
            'contractid' => $this->contractid
        ));

        if ($model == NULL)
        {
            $equipment = ContractEquipment::model()->find("contractid = '$this->contractid'");            
            if($equipment !=null){
                $model = new ContractLedger();
                $model->warehouse = '0000';
                $model->partno = $partno;
                $model->contractid = $this->contractid;
                $type = $this->getBillTypeText();                      
                $original = Equipment::model()->findByPk($equipment->equipmentid);
                $model->description =$equipment->serial.'  '.$original->description;                                
                $model->qty = 1;
                $model->cost = 0;
                $model->markupvalue = 190;
                $model->autoSetTaxed($this->custno);
                $model->noprint = 0;
                //$model->tax1 = 0;
                $model->save();
            }
            

        }
        $softModels = ContractSofwareMaintLedger::model()->findAll("contractid = '$this->contractid'");
        foreach($softModels as $item){
           $partno ='HIST2';
           $description='Software Platform:  '.$item->software_platform.' '.$item->software_product_id_1.' '.$item->software_id_2;
            $model = ContractLedger::model()->find('contractid=:contractid AND partno=:partno AND description=:description', array(
                'partno' => $partno,
                'contractid' => $this->contractid,
             'description'=>$description
            ));
            if(!$model){
                $model = new ContractLedger();
                $model->warehouse = '0000';
                $model->partno = $partno;
                $model->contractid = $this->contractid;
                $type = $this->getBillTypeText();
                $model->description =$description;
                $model->qty = 1;
                $model->cost = 0;
                $model->markupvalue = 190;
                $model->autoSetTaxed($this->custno);
                $model->noprint = 0;
                //$model->tax1 = 0;
                $model->price = 0;
                $model->save();
            }
        }

    }
    
     public function getTaxModel(){
        
        if($this->_tax==null){  
            $tax = Taxcode::model()->find('zipcode=:zipcode', array(
                'zipcode' =>  $this->getLocation()->zip
            ));
            if($tax!=null){
                $this->_tax = $tax;                
            }else{
                throw new CException('Can not find tax model for this contract'.$this->contractid.'. Please check this data again');    
            }
            
        }
        return $this->_tax;
    }

    
    public function isTaxNex(){
        $stateName = $this->getLocation()->state;
        $taxCodeNex =TaxcodeNex::model()->find("state='$stateName'");
        $this->_isTaxNex = (isset($taxCodeNex) && $taxCodeNex->active);
        return $this->_isTaxNex;
    }
    
    public function changeBillTypeEvent(){
        //delete old payment,
        if($this->isScheduleContract() == false){
            $invoiceNumberList = Yii::app()->db->createCommand('select * from tbl_contract_schedule where contractid=:id')->bindValue('id',$this->contractid)->queryAll();
            foreach($invoiceNumberList as $invoiceNumber){
                $invoice = Invoice::model()->find('invoice=:invoice',array(
                    'invoice'=>$invoiceNumber['invoice']
                ));
                if($invoice!=null){
                    $invoice->delete();
                }
                
            }
            Yii::app()->db->createCommand()->delete('tbl_contract_schedule', 'contractid=:contractid and billtype!=:billtype', array(
                'contractid' => $this->contractid,
                'billtype'   => $this->billtype
            ));
        }
    }

}
